package eecs285.proj4.gui;

//Class: EECS 285
//Project: 4 (Virtual Markerboard)
//Due Date: Monday December 6th, 2010

//NOTES: 
// This file defines the Markerboard class which handles all the functionality
// of the virtual markerboard.


import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
//import java.awt.image.BufferedImage;
//import java.awt.image.RenderedImage;

import javax.imageio.ImageIO;
import javax.swing.*;
//import javax.swing.plaf.ButtonUI;

import org.jivesoftware.smack.packet.Message;

//import sun.reflect.Reflection;
import eecs.net.xmpp.*;
import eecs.util.MException;


import static eecs.util.Utility.*;

// -----------------------------------------------------------------------------
// ----- BEGIN Class Definition (Markerboard) ----------------------------------

/**
 * A virtual markerboard that multiple users can connect to. Changes made by one
 * user are immediately visible to other users. Up to ten users are supported
 * simultaneously.
 * 
 * @author Hans Marquard
 * @author Easton Thomas
 * @author Vidal Borromeo
 * @author Matt Muccioli
 * @author Stubbed by Vidal Borromeo
 */
@SuppressWarnings("serial")
public class Markerboard extends JFrame
{
  public static final boolean DEBUG_MODE = true;
  public static final boolean SHOW_STACKTRACE = true;

  public static final String KEY_CHAT_AUTHOR = "ChatAuthor";
  public static final String KEY_CHAT_MESSAGE = "ChatMessage";
  public static final String KEY_DRAW_ACTION = "DrawAction";
  public static final String KEY_ANNOUNCE = "Announce";
  public static final String KEY_ANNOUNCE_RESPONSE = "AnnounceResponse";
  public static final String KEY_SYNC_REQUEST = "SyncRequest";
  public static final String KEY_SYNC_REQUESTER = "SyncRequester";
  public static final String KEY_SYNC_RESPONSE = "SyncResponse";
  public static final String KEY_SYNC_RESPONDER = "SyncResponder";
  public static final String KEY_SYNC_RESPONSE_USERS = "SyncResponseUserList";
  public static final String KEY_SYNC_RESPONSE_ACTIONCOUNT = "SyncResponseActionCount";
  public static final String KEY_SYNC_DONE = "SyncDone";
  public static final String KEY_HEARTBEAT = "HeartBeat";
  public static final String KEY_HEARTBEAT_SENDER = "HeartBeatSender";
  public static final String KEY_HEARTBEAT_RECIPIENT = "HeartBeatRecipient";
  public static final String KEY_ACTION_UNDO = "undo";
  Boolean outstandingAnnounce = false;
  Boolean outstandingSyncRequest = false;
  Set<String> userList = new TreeSet<String>();
  
  
  public static final String FILE_SESSIONID = "SessionID";
  public static final String FILE_USERNAME = "User";
  public static final String FILE_IMAGE = "Image";
  
  static final int DEFAULT_CANVAS_WIDTH = 800;
  static final int DEFAULT_CANVAS_HEIGHT = 600;
  //static final int DEFAULT_CANVAS_WIDTH = 1440;
  //static final int DEFAULT_CANVAS_HEIGHT = 900;
  int canvasWidth = DEFAULT_CANVAS_WIDTH;
  int canvasHeight = DEFAULT_CANVAS_HEIGHT;
  static final String WINDOW_TITLE = "Virtual Markerboard";
  JPanel mainPanel = new JPanel();

  JFrame mainFrame = null; // An alias for 'this' Frame, for clarity.
  JPanel topArea = new JPanel(); // Button/Toolbar area
  JPanel centerArea = new JPanel(); // The Canvas Area
  JPanel bottomArea = new JPanel(); // For anything
  JPanel leftArea = new JPanel(); // For anything
  JPanel rightArea = new JPanel(); // For anything

  JMenuItem loadMarkerboardMenuItem = new JMenuItem("Load Markerboard");
  JMenuItem saveMarkerboardMenuItem = new JMenuItem("Save Markerboard");
  JMenuItem saveImageMenuItem = new JMenuItem("Save Image");
  JMenuItem exitProgramMenuItem = new JMenuItem("Exit Program");
  JMenuItem resizeCanvasMenuItem = new JMenuItem("Resize Canvas");
  JMenuItem zoomInMenuItem = new JMenuItem("Zoom In");
  JMenuItem zoomOutMenuItem = new JMenuItem("Zoom Out");
  JMenuItem zoomResetMenuItem = new JMenuItem("Zoom to 100%");
  JMenu fileMenu = new JMenu("File");
  JMenu editMenu = new JMenu("Edit");
  JMenuBar mainMenuBar = new JMenuBar();
  
  
  java.net.URL greenUpArrowURL = getClass().getResource("images/UpArrow_Green.jpg");
   ImageIcon greenUpArrow = new ImageIcon(Toolkit.getDefaultToolkit().getImage(greenUpArrowURL));
  java.net.URL greenDownArrowURL = getClass().getResource("images/DownArrow_Green.jpg");
   ImageIcon greenDownArrow = new ImageIcon(Toolkit.getDefaultToolkit().getImage(greenDownArrowURL));
  java.net.URL yellowUpArrowURL = getClass().getResource("images/UpArrow_Yellow.jpg");
   ImageIcon yellowUpArrow = new ImageIcon(Toolkit.getDefaultToolkit().getImage(yellowUpArrowURL));
  java.net.URL yellowDownArrowURL = getClass().getResource("images/DownArrow_Yellow.jpg");
   ImageIcon yellowDownArrow = new ImageIcon(Toolkit.getDefaultToolkit().getImage(yellowDownArrowURL));
  
  //import Cursor Images
  java.net.URL MarkerURL = getClass().getResource("images/Marker.png");
  private Image Marker = Toolkit.getDefaultToolkit().getImage(MarkerURL);
  java.net.URL EraserURL = getClass().getResource("images/Eraser.png");
  Image Eraser = Toolkit.getDefaultToolkit().getImage(EraserURL);
  java.net.URL Marker_BlueURL = getClass().getResource("images/Marker_Blue.png");
  private Image Marker_Blue= Toolkit.getDefaultToolkit().getImage(Marker_BlueURL);
  java.net.URL Marker_GreenURL = getClass().getResource("images/Marker_Green.png");
  private Image Marker_Green = Toolkit.getDefaultToolkit().getImage(Marker_GreenURL);
  java.net.URL Marker_OrangeURL = getClass().getResource("images/Marker_Orange.png");
  private Image Marker_Orange = Toolkit.getDefaultToolkit().getImage(Marker_OrangeURL);
  java.net.URL Marker_PurpleURL = getClass().getResource("images/Marker_Purple.png");
  private Image Marker_Purple = Toolkit.getDefaultToolkit().getImage(Marker_PurpleURL);
  java.net.URL Marker_RedURL = getClass().getResource("images/Marker_Red.png");
  private Image Marker_Red = Toolkit.getDefaultToolkit().getImage(Marker_RedURL);
  java.net.URL Marker_YellowURL = getClass().getResource("images/Marker_Yellow.png");
  private Image Marker_Yellow = Toolkit.getDefaultToolkit().getImage(Marker_YellowURL);
  

  JPanel networkFlashPanel = new JPanel();
 
  
  JButton freeDrawButton;
  java.net.URL freeDrawURL = getClass().getResource("images/FreeDrawIcon.png");
  private Image freeDrawImg = Toolkit.getDefaultToolkit().getImage(freeDrawURL);
  JButton lineButton;
  java.net.URL lineURL = getClass().getResource("images/LineIcon.png");
  private Image lineImg = Toolkit.getDefaultToolkit().getImage(lineURL);
  JButton rectangleButton;
  java.net.URL rectangleURL = getClass()
      .getResource("images/RectangleIcon.png");
  private Image rectangleImg = Toolkit.getDefaultToolkit().getImage(
      rectangleURL);
  JButton circleButton;
  java.net.URL circleURL = getClass().getResource("images/CircleIcon.png");
  private Image circleImg = Toolkit.getDefaultToolkit().getImage(circleURL);
  JButton textButton;
  java.net.URL textURL = getClass().getResource("images/TextIcon.png");
  private Image textImg = Toolkit.getDefaultToolkit().getImage(textURL);
  JButton eraseButton;
  java.net.URL eraseURL = getClass().getResource("images/EraseIcon.png");
  private Image eraseImg = Toolkit.getDefaultToolkit().getImage(eraseURL);
  JButton clearButton;
  java.net.URL clearURL = getClass().getResource("images/ClearIcon.png");
  private Image clearImg = Toolkit.getDefaultToolkit().getImage(clearURL);
  JButton undoButton;
  java.net.URL undoURL = getClass().getResource("images/UndoIcon.png");
  private Image undoImg = Toolkit.getDefaultToolkit().getImage(undoURL);

  JPanel centerAreaPanel1 = new JPanel();
  
  JPanel leftAreaNorthPanel = new JPanel();
  JPanel sessionIDPanel = new JPanel();
  JLabel sessionIDLabel;
  JTextField sessionIDTextField;
  JPanel userNamePanel = new JPanel();
  JLabel userNameLabel;
  JTextField userNameTextField;
  JButton connectButton = new JButton("Connect");
  JPanel leftAreaCenterPanel = new JPanel();
  JButton disconnectButton = new JButton("Disconnect");;
  JTextArea chatArea;
  JScrollPane chatScrollPane;
  JTextArea typingArea;
  JScrollPane typingScrollPane;
  JPanel leftAreaSouthPanel = new JPanel();
  JButton sendButton;
  
  // Right Area
  JPanel rightAreaPanel1 = new JPanel();
  JPanel colorChooserPanel = new JPanel();
  JLabel colorChooserLabel;
  JComboBox colorChooserComboBox;
  JPanel strokeChooserPanel = new JPanel();
  JLabel strokeChooserLabel;
  JTextField strokeChooserTextField;
  
  //Cursors
  Cursor Eraser_Curser;
  Cursor Marker_Curser;
  Cursor Marker_Black_Curser;
  Cursor Marker_Blue_Curser;
  Cursor Marker_Green_Curser;
  Cursor Marker_Orange_Curser;
  Cursor Marker_Purple_Curser;
  Cursor Marker_Red_Curser;
  Cursor Marker_Yellow_Curser;
  
  //Animators
  EECSAnimator animateIn;
  EECSAnimator animateOut;

  MarkerboardListener mListener = null;

  JScrollPane canvasScrollPane = null;
  Graphics2D canvasGraphics = null;

  // markerboard_canvas is for passing to listener
  MarkerboardCanvas markerboard_canvas = new MarkerboardCanvas(this);
  // canvas is for passing to GUI
  Canvas canvas = markerboard_canvas;
  // Canvas canvas = new Canvas();


  EECSXMPPConnection connection = new EECSXMPPConnection();
  String sessionID = null;

  // ---------------------------------------------------------------------------

  public Markerboard()
  {
    super(WINDOW_TITLE);
    mainFrame = this; // Set an alias for clarity
    mainFrame.setLayout(new BorderLayout());
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mListener = new MarkerboardListener(this, markerboard_canvas);

    mainFrame.addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent wEvent)
      {
        exitProgram();
        assert "Should Not Get Here" == null;
      }
    });
    

    debug("Look and Feel: " + UIManager.getSystemLookAndFeelClassName());
    // SET A LOOK AND FEEL
//    try
//    {
//         //You can set a specific one, or just get the system default.
//      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//    }
//    catch( ClassNotFoundException e )
//    {
//      // TODO Auto-generated catch block
//      e.printStackTrace();
//    }
//    catch( InstantiationException e )
//    {
//      // TODO Auto-generated catch block
//      e.printStackTrace();
//    }
//    catch( IllegalAccessException e )
//    {
//      // TODO Auto-generated catch block
//      e.printStackTrace();
//    }
//    catch( UnsupportedLookAndFeelException e )
//    {
//      // TODO Auto-generated catch block
//      e.printStackTrace();
//    }
    
    
    //Initialize Animator
    String[] animatorStringIn = new String[2];
    animatorStringIn[0] = "images/DownArrow_Green.png";
    animatorStringIn[1] = "images/DownArrow_Yellow.png";
    animateIn = new EECSAnimator(animatorStringIn);
    
    String[] animatorStringOut = new String[2];
    animatorStringOut[0] = "images/UpArrow_Green.png";
    animatorStringOut[1] = "images/UpArrow_Yellow.png";
    animateOut = new EECSAnimator(animatorStringOut);

    //Set Custom Cursors in Canvas
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Marker_Black_Curser = toolkit.createCustomCursor(Marker, new Point(canvas.getX(),canvas.getY()), "Marker");
    Eraser_Curser = toolkit.createCustomCursor(Eraser, new Point(canvas.getX(),canvas.getY()), "Eraser");
    Marker_Blue_Curser = toolkit.createCustomCursor(Marker_Blue, new Point(canvas.getX(),canvas.getY()), "Marker_Blue");
    Marker_Green_Curser = toolkit.createCustomCursor(Marker_Green, new Point(canvas.getX(),canvas.getY()), "Marker_Green");
    Marker_Orange_Curser = toolkit.createCustomCursor(Marker_Orange, new Point(canvas.getX(),canvas.getY()), "Marker_Orange");
    Marker_Purple_Curser = toolkit.createCustomCursor(Marker_Purple, new Point(canvas.getX(),canvas.getY()), "Marker_Purple");
    Marker_Red_Curser = toolkit.createCustomCursor(Marker_Red, new Point(canvas.getX(),canvas.getY()), "Marker_Red");
    Marker_Yellow_Curser = toolkit.createCustomCursor(Marker_Yellow, new Point(canvas.getX(),canvas.getY()), "Marker_Yellow");
    Marker_Curser = Marker_Black_Curser;
    canvas.setCursor(Marker_Curser);
    
    
    // canvasGraphics = new Graphics2D(); // Check How To Actually Use This

    // TODO: Lookup how to work with/between a Canvas object and Graphics
    // object.
    // TODO: Make small area in corner that shows incoming/outgoing activity.
    

    // Add Menu Bar
    fileMenu.add(loadMarkerboardMenuItem);
    fileMenu.add(saveMarkerboardMenuItem);
    fileMenu.add(saveImageMenuItem);
    fileMenu.add(exitProgramMenuItem);
    editMenu.add(zoomInMenuItem);
    editMenu.add(zoomOutMenuItem);
    editMenu.add(zoomResetMenuItem);
    editMenu.add(resizeCanvasMenuItem);
    mainMenuBar.add(fileMenu);
    //mainMenuBar.add(editMenu);
    mainFrame.setJMenuBar(mainMenuBar);

    // Add mListener for Menu Bar.
    loadMarkerboardMenuItem.addActionListener(mListener);
    saveMarkerboardMenuItem.addActionListener(mListener);
    saveImageMenuItem.addActionListener(mListener);
    exitProgramMenuItem.addActionListener(mListener);
    resizeCanvasMenuItem.addActionListener(mListener);
    zoomInMenuItem.addActionListener(mListener);
    zoomOutMenuItem.addActionListener(mListener);
    zoomResetMenuItem.addActionListener(mListener);

    // Add the buttons to the top area.
    topArea.setLayout(new FlowLayout());
    freeDrawButton = new JButton(new ImageIcon(freeDrawImg));
    freeDrawButton.setBackground(Color.GRAY);
    freeDrawButton.setToolTipText("Free Draw");
    topArea.add(freeDrawButton);
    lineButton = new JButton(new ImageIcon(lineImg));
    lineButton.setToolTipText("Line");
    topArea.add(lineButton);
    rectangleButton = new JButton(new ImageIcon(rectangleImg));
    rectangleButton.setToolTipText("Rectangle");
    topArea.add(rectangleButton);
    circleButton = new JButton(new ImageIcon(circleImg));
    circleButton.setToolTipText("Oval");
    topArea.add(circleButton);
    textButton = new JButton(new ImageIcon(textImg));
    textButton.setToolTipText("Text");
    topArea.add(textButton);
    eraseButton = new JButton(new ImageIcon(eraseImg));
    eraseButton.setToolTipText("Eraser");
    topArea.add(eraseButton);
    clearButton = new JButton(new ImageIcon(clearImg));
    clearButton.setToolTipText("Clear Canvas");
    topArea.add(clearButton);
    undoButton = new JButton(new ImageIcon(undoImg));
    undoButton.setToolTipText("Undo");
    topArea.add(undoButton);

    // Add mListener for Buttons in top area.
    freeDrawButton.addActionListener(mListener);
    lineButton.addActionListener(mListener);
    rectangleButton.addActionListener(mListener);
    circleButton.addActionListener(mListener);
    textButton.addActionListener(mListener);
    eraseButton.addActionListener(mListener);
    clearButton.addActionListener(mListener);
    undoButton.addActionListener(mListener);

    // Add the canvas to the central area.
    canvas.setSize(canvasWidth, canvasHeight); // Set initial canvas size.
    canvas.setBackground(Color.white); // Make canvas white.
    //canvasScrollPane = new JScrollPane(canvas);
    //canvasScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
    //canvasScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    
    
    //centerArea.add(topArea);  
    centerArea.add(canvas);
    //centerArea.setLayout(new BorderLayout());
    //centerArea.add(topArea, BorderLayout.NORTH); 
    //centerAreaPanel1.add(canvas, BorderLayout.NORTH);
    //centerArea.add(centerAreaPanel1, BorderLayout.CENTER);  
    //centerArea.add(canvasScrollPane);

    // Add leftArea Panels
    leftArea.setLayout(new BorderLayout());
    leftAreaNorthPanel.setLayout(new BorderLayout());
    leftAreaCenterPanel.setLayout(new BorderLayout());
    leftAreaSouthPanel.setLayout(new BorderLayout());

    // Left Area: NORTH Panel
    sessionIDPanel.setLayout(new FlowLayout());
    sessionIDLabel = new JLabel("Session ID:");
    sessionIDPanel.add(sessionIDLabel);
    sessionIDTextField = new JTextField(EECSXMPPConnection.generateID(), 14);
    // sessionIDTextField.setText(EECSXMPPConnection.generateID());
    sessionIDPanel.add(sessionIDTextField);
    leftAreaNorthPanel.add(sessionIDPanel, BorderLayout.NORTH);

    userNamePanel.setLayout(new FlowLayout());
    userNameLabel = new JLabel("User Name:");
    userNamePanel.add(userNameLabel);
    userNameTextField = new JTextField("Your Name Here", 14);
    // userNameTextField.setText("Your Name Here");
    userNamePanel.add(userNameTextField);
    leftAreaNorthPanel.add(userNamePanel, BorderLayout.CENTER);

    leftAreaNorthPanel.add(connectButton, BorderLayout.SOUTH);

    // Left Area: CENTER Panel
    disconnectButton.setEnabled(false);
    leftAreaCenterPanel.add(disconnectButton, BorderLayout.NORTH);
    chatArea = new JTextArea();
    chatArea.setBorder(BorderFactory.createTitledBorder(
        BorderFactory.createLineBorder(Color.BLACK), "CHAT AREA"));
    chatArea.setLineWrap(true);
    chatArea.setWrapStyleWord(true);
    chatArea.setEditable(false);
    chatArea.setBackground(null);
    chatScrollPane = new JScrollPane(chatArea);
    chatScrollPane
        .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    leftAreaCenterPanel.add(chatScrollPane, BorderLayout.CENTER);
    typingArea = new JTextArea(3, 20);
    typingArea.setBorder(BorderFactory.createTitledBorder(
        BorderFactory.createLineBorder(Color.BLACK), "TYPING AREA"));
    typingArea.setLineWrap(true);
    typingArea.setWrapStyleWord(true);
    typingArea.setEditable(false);
    typingArea.setBackground(null);
    typingScrollPane = new JScrollPane(typingArea);
    typingScrollPane
        .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    leftAreaCenterPanel.add(typingScrollPane, BorderLayout.SOUTH);
    
    // typingArea KeyListener Code
    typingArea.addKeyListener(
        new KeyAdapter()
        {
          public void keyPressed( KeyEvent e )
          {
            if( e.getKeyCode() == KeyEvent.VK_ENTER)
            {
              sendChatMessage();
              e.consume();
            }
          }
        }
    );

    // Left Area: SOUTH Panel
    sendButton = new JButton("Send");
    sendButton.setEnabled(false);
    leftAreaSouthPanel.add(sendButton, BorderLayout.SOUTH);

    // Add Panels to leftArea.
    leftArea.add(leftAreaNorthPanel, BorderLayout.NORTH);
    leftArea.add(leftAreaCenterPanel, BorderLayout.CENTER);
    leftArea.add(leftAreaSouthPanel, BorderLayout.SOUTH);

    // Add mListener for leftArea.
    connectButton.addActionListener(mListener);
    disconnectButton.addActionListener(mListener);
    sendButton.addActionListener(mListener);

    // Right Area: Panel Setup
    rightArea.setLayout(new BorderLayout());
    rightAreaPanel1.setLayout(new BorderLayout());

    // Right Area: Stroke Size Label and Text Field.
    strokeChooserPanel.setLayout(new BorderLayout());
    strokeChooserLabel = new JLabel("Stroke Size:");
    strokeChooserTextField = new JTextField();
    strokeChooserTextField.setText("4");
    strokeChooserPanel.add(strokeChooserLabel, BorderLayout.NORTH);
    strokeChooserPanel.add(strokeChooserTextField, BorderLayout.SOUTH);
    
    // Right Area: Color Chooser ComboBox
    colorChooserPanel.setLayout(new BorderLayout());
    colorChooserComboBox = new JComboBox();
    colorChooserComboBox.addItem("Black");
    colorChooserComboBox.addItem("Pink");
    colorChooserComboBox.addItem("Red");
    colorChooserComboBox.addItem("Orange");
    colorChooserComboBox.addItem("Yellow");
    colorChooserComboBox.addItem("Green");
    colorChooserComboBox.addItem("Cyan");
    colorChooserComboBox.addItem("Blue");
    colorChooserComboBox.addItem("Magenta");
    colorChooserComboBox.addItem("Gray");
    colorChooserLabel = new JLabel("Color:");
    colorChooserPanel.add(colorChooserLabel, BorderLayout.NORTH);
    colorChooserPanel.add(colorChooserComboBox, BorderLayout.SOUTH);
    colorChooserComboBox.addActionListener(mListener);
    
    // Right Area: Flash Panel
    /*networkFlashPanel.setLayout(new BoxLayout(networkFlashPanel,
        BoxLayout.PAGE_AXIS));*/
    //incomingFlashLabel = new JLabel(new ImageIcon(incomingFlashImg));
    networkFlashPanel.add(animateIn);
    networkFlashPanel.add(animateOut);
    //outgoingFlashLabel = new JLabel(new ImageIcon(outgoingFlashImg));
    networkFlashPanel.setBorder(BorderFactory.createTitledBorder(
        BorderFactory.createLineBorder(Color.BLACK), "Network"));
    
    // Right Area: Add Panels
    rightArea.add(strokeChooserPanel, BorderLayout.NORTH);
    rightAreaPanel1.add(colorChooserPanel, BorderLayout.NORTH);
    rightArea.add(rightAreaPanel1, BorderLayout.CENTER);
    rightArea.add(networkFlashPanel, BorderLayout.SOUTH);
    
    // Add the different areas into the frame.
    mainFrame.add(topArea, BorderLayout.NORTH);
    mainFrame.add(centerArea, BorderLayout.CENTER);
    mainFrame.add(bottomArea, BorderLayout.SOUTH);
    mainFrame.add(leftArea, BorderLayout.WEST);
    mainFrame.add(rightArea, BorderLayout.EAST);
    mainFrame.pack();
    mainFrame.setVisible(true);
    markerboard_canvas.createBufferStrategy(2); // sets up double buffering

    
    
    // start the thread that upgrades board
    Thread thread = new Thread(markerboard_canvas);
    thread.start();
  }// Ctor

//---------------------------------------------------------------------------
  public Cursor setCursorColor()
  {
    switch (colorChooserComboBox.getSelectedIndex())
    {
      case 0:
      {
        return Marker_Black_Curser;
      }
      case 1:
      {
        System.out.println("Pink Selected");
        return Marker_Red_Curser;
      }
      case 2:
      {
        return Marker_Red_Curser;
      }
      case 3:
      {
       return Marker_Orange_Curser;
      }
      case 4:
      {
        return Marker_Yellow_Curser;
      }
      case 5:
      {
        return Marker_Green_Curser;
      }
      case 6:
      {
        return Marker_Blue_Curser;
      }
      case 7:
      {
        return Marker_Blue_Curser;
      }
      case 8:
      {
       return Marker_Purple_Curser;
      }
      case 9:
      {
        return Marker_Black_Curser;
      }
      default:
      {
        return Marker_Red_Curser;
      }
    }
  }
  // ---------------------------------------------------------------------------

  /**
   * Creates the XMPP connection using the specified Markerboard ID.
   * <b>Note:</b> The sessionID should not be changed while connected. The
   * connection uses the sessionID to discard packets not associated with the
   * current session.
   * 
   * @param sessionID_
   *          The ID to use for this Markerboard. Other clients use this to
   *          share the markerboard.
   * @return <code>true</code>, disconnect was successful; <code>false</code>,
   *         disconnect was not successful.
   * @author Vidal Borromeo
   */
  public boolean connect(String sessionID_)
  {
    addMessage(null, "Connecting...");
    debug("Connecting...");
    
    // Create the networking connection.
    try
    {
      if( connection == null )
        connection = new EECSXMPPConnection();

      connection.connect(sessionID_, getUser(), mListener);

      assert (connection.isConnected());
    }// try
    catch( MException e )
    {
      addMessage(null, e.getMessage());
      return false;
    }// catch
    
    //assert connection.isConnected();
    

    sendAnnounce();
    typingArea.setText("<I have joined.>");
    sendChatMessage();

    debug("Connect was successful.");
    return true;
  }// connect

  // ---------------------------------------------------------------------------

  /**
   * Disconnects the current XMPP connection.
   * 
   * @return <code>true</code>, disconnect was successful; <code>false</code>,
   *         disconnect was not successful.
   * 
   * @author Vidal Borromeo
   */
  public boolean disconnect()
  {
    debug("Disconnecting...");
    synchronized( connection )
    {
      if( connection == null )
      {
        debug("Pointer was null.");
        return false;
      }
      typingArea.setText("<I am leaving.>");
      sendChatMessage();

      if( !connection.disconnect() )
      {
        debug("Disconnect was Not successful.");
        return false;
      }
    }
    return true;
  }// disconnect

  // ---------------------------------------------------------------------------

  public void sendAnnounce()
  {
    synchronized( outstandingAnnounce )
    {
      outstandingAnnounce = true;
      try
      {
        connection.broadcast(KEY_ANNOUNCE, getUser());
      }
      catch( IOException e )
      {
        debug("Could not send Announce.");
      }
    }// sync

  }// sendAnnounce()
  
  // ---------------------------------------------------------------------------

  public void sendSyncRequest(String first_responder)
  {
    synchronized( outstandingSyncRequest )
    {
      outstandingSyncRequest = true;
      try
      {
        connection.broadcast(KEY_SYNC_REQUEST, first_responder, KEY_SYNC_REQUESTER,
            getUser());
      }
      catch( IOException e )
      {
        debug("Could not send Sync Request.");
      }
    }// sync

  }// sendSyncRequest()

  // ---------------------------------------------------------------------------


  public String getSessionID()
  {
    return sessionIDTextField.getText();
  }// getSessionID

  // ---------------------------------------------------------------------------

  /**
   * Returns the text in userNameTextField, unless the text equals one of the if statements.
   * 
   * @author Matt Muccioli
   * @author Stubbed by Matt Muccioli
   */
  public String getUser()
  {
    if (userNameTextField.getText().equalsIgnoreCase("Your Name Here")){
      return "Lazy Person";
    }
    else if (userNameTextField.getText().equalsIgnoreCase("")){
      return "Anonymous";
    }
    else if (userNameTextField.getText().equalsIgnoreCase(" ")){
      return "My name is only one space";
    }
    else if (userNameTextField.getText().equalsIgnoreCase("Matt Muccioli")){
      return "Mr. Awesome";
    }
    else if (userNameTextField.getText().equalsIgnoreCase("Hans")){
      return "Old Man Hans";
    }
    else if (userNameTextField.getText().equalsIgnoreCase("Backwards")){
      return "sdrawkcaB";
    }
    return userNameTextField.getText();
  }// getUser

  // ---------------------------------------------------------------------------

  // ---------------------------------------------------------------------------

  public void setCanvasWidth(int width_)
  {
    canvasWidth = width_;
    // TODO: This should change the canvas, and the Frame.
  }// setCanvasWidth

  // ---------------------------------------------------------------------------

  public void setCanvasHeight(int height_)
  {
    canvasHeight = height_;
    // TODO: This should change the canvas, and the Frame.
  }// setCanvasHeight

  // ---------------------------------------------------------------------------

  public int getCanvasWidth()
  {
    return canvasWidth;
  }// getCanvasWidth

  // ---------------------------------------------------------------------------

  public int getCanvasHeight()
  {
    return canvasHeight;
  }// getCanvasHeight

  // ---------------------------------------------------------------------------

  Graphics2D getGraphicsObject()
  {
    return canvasGraphics;
  }

  // ---------------------------------------------------------------------------

  /**
   * Opens a file dialog where the user can select a saved Markerboard file to
   * open.
   * 
   * @author [Implementor Goes Here]
   * @author Stubbed by Vidal Borromeo
   */
  void loadMarkerboard()
  {
    if(connection.isConnected())
    {
      doError(this, "Cannot load while connected.", "Load Error");
      return;
    }
    

    String fileName;
    JFileChooser jfc = new JFileChooser(".");
    jfc.addChoosableFileFilter(new MarkerboardFileFilter());
    
    if( jfc.showDialog(this, "Load") != JFileChooser.APPROVE_OPTION )
    {
      debug("User cancelled load.");
      return;
    }

    fileName = jfc.getSelectedFile().getPath();
    
    debug("Loading Markerboard from: " + fileName);
    
    String user;
    String session;
    ObjectInputStream inputStream = null;   
    try
    {
      inputStream = new ObjectInputStream(new FileInputStream(fileName));
      session = (String) inputStream.readObject();
      sessionIDTextField.setText(session);
      user = (String) inputStream.readObject();
      userNameTextField.setText(user);
      markerboard_canvas.set_image((byte[]) inputStream.readObject());
    }
    catch( FileNotFoundException e )
    {
      //String msg = "Cannot find file: " + fileName;
      String msg = e.getLocalizedMessage();
      // Construct but don't throw. Uses StackTraceElements in place of
      // printStackTrace().
      new MException(msg);
      doError(this, msg, "File Error");
      return;

    }
    catch( IOException e )
    {
      String msg = "Unable to read data from: " + fileName;
      new MException(msg); // construct only
      doError(this,msg, "File Error");
      return;
    }
    catch( ClassNotFoundException e )
    {
      String msg = "Unknown class encountered in ObjectStream.";
      new MException(msg);
      doError(this,msg, "File Error");
      return;
    }
  }// loadMarkerboard

  // ---------------------------------------------------------------------------

  /**
   * Opens a file dialog where the user can save the current Markerboard.
   * 
   * @author [Implementor Goes Here]
   * @author Stubbed by Vidal Borromeo
   */
  void saveMarkerboard()
  {
    JFileChooser jfc = new JFileChooser(".");
    jfc.addChoosableFileFilter(new MarkerboardFileFilter());
    
    String fileName;


    if( jfc.showDialog(this, "Save") != JFileChooser.APPROVE_OPTION )
    {
      debug("User cancelled save.");
      return;
    }

    fileName = jfc.getSelectedFile().getPath();

    int dotPos = fileName.lastIndexOf(".mkb");
//    debug(""+dotPos);
//    debug(""+fileName.length());
    if( dotPos != fileName.length()-".mkb".length() )
      fileName += ".mkb";
      
    debug("Saving Markerboard to: " + fileName);
    ObjectOutputStream outputStream = null;
    
    
    try
    {

      // Construct the LineNumberReader object
      outputStream = new ObjectOutputStream(new FileOutputStream(fileName));

      outputStream.writeObject(getSessionID());
      outputStream.writeObject(getUser());
      outputStream.writeObject(markerboard_canvas.get_image());
      //outputStream.writeObject(save);

    }// try
    catch( Exception e )
    {
      String msg = e.getLocalizedMessage();
      new MException(msg); // construct only.
      doError(this,msg, "File Error");
      return;
    }
    finally
    {
      try
      {
        if( outputStream != null )
        {
          outputStream.flush();
          outputStream.close();
        }
      }
      catch( IOException ex )
      {
        //ex.printStackTrace();
      }
    }// finally
 
  }// saveMarkerboard

  // ---------------------------------------------------------------------------

  /**
   * Allows the user to save an image file of the current canvas. Opens a dialog
   * where the user can select the file format (i.e. jpg, gif, etc.) and
   * location.
   * 
   * @author Hans Marquard
   * @author Stubbed by Vidal Borromeo
   */
  void saveImage()
  {
  //Create a file chooser
    JFileChooser chooser = new JFileChooser(".");
    chooser.addChoosableFileFilter(new ImageFileFilter());
    int returnVal = chooser.showSaveDialog(this);
    
    String fileName = chooser.getSelectedFile().getPath();
    
    
    
    if(returnVal == JFileChooser.APPROVE_OPTION) {
      try 
      {
//        Image img = markerboard_canvas.get_image().getImage();
//
//        BufferedImage bi = new BufferedImage(img.getWidth(null),img.getHeight(null),
//                                             BufferedImage.TYPE_INT_RGB);
//        Graphics2D g2 = bi.createGraphics();
//        // Draw img into bi so we can write it to file.
//        g2.drawImage(img, 0, 0, null);
//        g2.dispose();
//        // Now bi contains the img.
//        //ImageIO.write(bi, "JPG", chooser.getSelectedFile());
        chooser.getFileFilter().getDescription();
        
        int dotPos = fileName.lastIndexOf(".png");

      if( dotPos != fileName.length()-".png".length() )
        fileName += ".png";
      
        //ImageIO.write(markerboard_canvas.getBufImage(), "PNG", chooser.getSelectedFile());
      ImageIO.write(markerboard_canvas.getBufImage(), "PNG", new File(fileName));
      } 
      catch(IOException e) 
      {
        System.out.println("Write error for " + chooser.getSelectedFile().getPath() +
                           ": " + e.getMessage());
      }
    }
 
  }// saveImage

  // ---------------------------------------------------------------------------

  /**
   * Handles any housekeeping before finally closing. Sends 'leaving' chat
   * message.
   * 
   * @author Matthew Muccioli
   * @author Stubbed by Matthew Muccioli
   */
  void exitProgram()
  {
    disconnect();
    System.exit(0);
  }// exitProgram

  // ---------------------------------------------------------------------------
  /**
   * Zooms in on the current canvas.
   * 
   * @author [Implementor Goes Here]
   * @author Stubbed by Vidal Borromeo
   */
  void zoomIn()
  {
    // TODO: Implement this
  }// zoomIn

  // ---------------------------------------------------------------------------

  /**
   * Zooms out on the current canvas.
   * 
   * @author [Implementor Goes Here]
   * @author Stubbed by Vidal Borromeo
   */
  void zoomOut()
  {
    // TODO: Implement this
  }// zoomOut

  // ---------------------------------------------------------------------------

  /**
   * Resets the currnet zoom level for this user. Scales the canvas to fit
   * completely in the confines of it's portion or the current frame.
   * 
   * @author [Implementor Goes Here]
   * @author Stubbed by Vidal Borromeo
   */
  void zoomReset()
  {
    // TODO: Implement this
  }// zoomReset

  // ---------------------------------------------------------------------------

  /**
   * Allows the user to redimension the canvas. Prompts for new height/width.
   * 
   * @author [Implementor Goes Here]
   * @author Stubbed by Vidal Borromeo
   */
  void resizeCanvas()
  {
    // TODO: Implement this
  }// resizeCanvas

  // ---------------------------------------------------------------------------

  // ---------------------------------------------------------------------------

  /**
   * Sends the current text in the chat box..
   * 
   * @author Vidal Borromeo
   */
  void sendChatMessage()
  {
    String msg = typingArea.getText();
    msg.trim();
    if( msg.length() < 1 )
    {
      debug("Empty chat text. Not sending.");
      return;
    }
    
    String author = getUser();
    typingArea.setText("");
    Map<String, Object> map = new TreeMap<String, Object>();
    map.put(KEY_CHAT_MESSAGE, msg);
    map.put(KEY_CHAT_AUTHOR, author);
    try
    {
      addMessage(author, msg); // Send to self.
      synchronized(connection)
      {
        connection.broadcast(map); // Send to everyone else.
      }
    }
    catch( Exception e )
    {

      // e.printStackTrace();
      addMessage(null, "Could not send message.");
      debug("Could not send chat message. " + e.getClass().getSimpleName());
    }
  }// sendChatMessage

  // ---------------------------------------------------------------------------

  public void addMessage(String user_, String msg)
  {
    if( user_ == null )
    {
      msg = "<" + msg + ">";
    }
    else
    {
      msg = user_ + ": " + msg;
    }
    String temp = chatArea.getText();
    chatArea.setText( ( temp.length()<1 ? "" : temp+"\n") + msg);
  }// addMessage

  // ---------------------------------------------------------------------------

}// Markerboard

// ----- END Class Definition (Markerboard) ------------------------------------
// -----------------------------------------------------------------------------
